<script setup lang="ts">
import { message } from '@/common/message'
import { isNotEmpty, to } from '@/tools'
import uvCheckboxGroup from '@/uni_modules/uv-checkbox/components/uv-checkbox-group/uv-checkbox-group.vue'
import uvCheckbox from '@/uni_modules/uv-checkbox/components/uv-checkbox/uv-checkbox.vue'
import uvInput from '@/uni_modules/uv-input/components/uv-input/uv-input.vue'
import uvRadioGroup from '@/uni_modules/uv-radio/components/uv-radio-group/uv-radio-group.vue'
import uvRadio from '@/uni_modules/uv-radio/components/uv-radio/uv-radio.vue'
import uvTextarea from '@/uni_modules/uv-textarea/components/uv-textarea/uv-textarea.vue'
import type { DynamicForm, FormColumn, UvFormInstance } from './common'
// import uvUpload from '@/uni_modules/uv-upload/components/uv-upload/uv-upload.vue'

defineOptions({
  name: 'DynamicForm',
});

const props = withDefaults(
  defineProps<{
    columns: DynamicForm
    showSubmit?: boolean
    showReset?: boolean
    inline?: boolean
    modelValue?: Record<string, any>
  }>(),
  {
    showSubmit: true,
    showReset: true,
    inline: false,
    modelValue: () => ({}),
  },
);
const emits = defineEmits<{
  (e: 'submit', form: Record<string, any>): void
  (e: 'select', action: any, key: string): void // 添加 select 事件
  (e: 'confirm', value: any): void
  (e: 'actionSheet', value: any): void
  (e: 'update:modelValue', value: Record<string, any>): void
}>();

const openActionSheet = (column: FormColumn<Record<string, any>>) => {
  emits('actionSheet', column);
  uni.$emit(
    'openActionSheet',
    Object.assign({}, column, { value: form[column.key] }),
  );
};

const uvFormInstance = ref<UvFormInstance>();

const form = reactive<Record<string, any>>(
  props.columns.reduce(
    (pre, cur) => {
      if (
        cur.component === 'RadioGroup'
        || cur.component === 'Select'
        || cur.component === 'Input'
        || cur.component === 'Textarea'
      ) {
        pre[cur.key] = ''
      }
      else if (cur.component === 'CheckboxGroup') {
        pre[cur.key] = [];
      }
      else {
        pre[cur.key] = null;
      }
      return pre;
    },
    {} as unknown as any,
  ),
);

const getRules = () => {
  return props.columns.reduce(
    (pre, cur) => {
      if (cur.rule) {
        pre[cur.key] = cur.rule;
      }
      return pre;
    },
    {} as unknown as Record<string, any> | any,
  );
};

const submit = () => {
  uvFormInstance.value
    ?.validate()
    .then(() => {
      emits('submit', form);
    })
    .catch(() => {
      message.error('请完善表单信息')
    });
};

const reset = () => {
  uvFormInstance.value?.resetFields();
  uvFormInstance.value?.clearValidate();
};
const getFormValues = () => {
  const result: Record<string, any> = {};
  props.columns.forEach((column) => {
    result[column.key] = form[column.key];
  })
  return result;
};
const getFormValuesWithValid = async () => {
  if (!uvFormInstance.value) {
    return;
  }

  const [err] = await to(uvFormInstance.value.validate());

  if (err) {
    return message.error('请完善表单信息')
  }
  return form;
};

const setFormValues = (values: Record<string, any>) => {
  Object.keys(values).forEach((key) => {
    isNotEmpty(values[key]) && (form[key] = values[key]);
  })
  emits('update:modelValue', form);
};

watch(
  () => form,
  (newVal) => {
    emits('update:modelValue', newVal);
  },
  { deep: true },
);

watch(
  () => props.modelValue,
  (newVal) => {
    if (newVal) {
      Object.keys(newVal).forEach((key) => {
        form[key] = newVal[key];
      })
    }
  },
  { deep: true, immediate: true },
);

onMounted(() => {
  uvFormInstance.value?.setRules(getRules());
})

defineExpose({
  setFormValues,
  getFormValues,
  getFormValuesWithValid,
  submit,
  /// uvFormInstance: uvFormInstance.value,
  validate: () => {
    if (
      uvFormInstance.value
      && typeof uvFormInstance.value.validate === 'function'
    ) {
      return uvFormInstance.value.validate();
    }
    return Promise.reject(new Error('表单实例未初始化'));
  },
  setRules: (rules: any) => {
    if (
      uvFormInstance.value
      && typeof uvFormInstance.value.setRules === 'function'
    ) {
      return uvFormInstance.value.setRules(rules);
    }
  },
  validateField: (field: string) => {
    if (
      uvFormInstance.value
      && typeof uvFormInstance.value.validateField === 'function'
    ) {
      return uvFormInstance.value.validateField(field);
    }
  },
  resetFields: () => {
    if (
      uvFormInstance.value
      && typeof uvFormInstance.value.resetFields === 'function'
    ) {
      return uvFormInstance.value.resetFields();
    }
  },
  clearValidate: () => {
    if (
      uvFormInstance.value
      && typeof uvFormInstance.value.clearValidate === 'function'
    ) {
      return uvFormInstance.value.clearValidate();
    }
  },
});
</script>

<template>
  <uv-form
    ref="uvFormInstance"
    labelPosition="left"
    :model="form"
    v-bind="$attrs || {}"
  >
    <template
      v-for="(column, index) in columns"
      :key="`${column.key}-${index}`"
    >
      <view
        v-if="column.key === 'custom-divider'"
        class="my-[16rpx] h-[1rpx] w-full bg-[#f6f6f6]"
        :style="column.componentProps?.customStyle"
      />
      <view
        v-else-if="column.key === 'common-divider'"
        class="h-[21px] w-full bg-white px-[24rpx] py-[20rpx]"
        :style="column.formItemProps?.customStyle || {}"
      >
        <view
          class="h-px w-full bg-[#f6f6f6]"
          :style="column.componentProps?.customStyle"
        />
      </view>
      <uv-form-item
        v-else-if="column.vShow !== false"
        v-bind="column.formItemProps"
        :prop="column.formItemProps.prop || column.key"
        :required="column.required || false"
      >
        <!-- 自定义标签插槽 -->
        <template #label>
          <slot
            :name="`label-${column.key}`"
            :formModel="form"
            :field="column.key"
          >
            {{ column.formItemProps?.label }}
            <text v-if="column.required" class="ml-[4rpx] text-[#f56c6c]">
              *
            </text>
          </slot>
        </template>

        <template v-if="column.component === 'Input'">
          <uv-input
            v-model="form[column.key]"
            v-bind="column.componentProps || {}"
          >
            <template #suffix>
              <view v-if="column.componentProps?.suffixText">
                {{ column.componentProps?.suffixText }}
              </view>
            </template>
          </uv-input>
        </template>
        <template v-else-if="column.component === 'Switch'">
          <view
            class="flex w-full items-center"
            :style="{
              justifyContent: column.componentProps?.align || 'flex-end',
            }"
          >
            <uv-switch
              v-model="form[column.key]"
              v-bind="column.componentProps || {}"
            />
          </view>
        </template>
        <template v-else-if="column.component === 'Textarea'">
          <uvTextarea
            v-model="form[column.key]"
            v-bind="column.componentProps || {}"
          />
        </template>
        <template v-else-if="column.component === 'Select'">
          <view
            style="width: 100%"
            class="flex items-center justify-end"
            @tap.stop="openActionSheet(column)"
          >
            <view
              v-if="form[column.key]?.length > 20"
              :style="column.componentProps?.customStyle"
              class="line-clamp-2"
            >
              {{ form[column.key] }}
            </view>
            <uv-input
              v-else
              v-bind="column.componentProps || {}"
              :value="column.componentProps?.transformPreview ? column.componentProps?.transformPreview(form[column.key]) : form[column.key]"
            >
              <template #suffix>
                <div
                  v-if="column.componentProps?.suffixText"
                  class="mr-[20rpx]"
                >
                  {{ column.componentProps?.suffixText }}
                </div>
                <image
                  v-if="column.componentProps?.suffixImage"
                  class="mr-[20rpx]"
                  :src="column.componentProps?.suffixImage"
                  mode="widthFix"
                  style="width: 68rpx; height: 68rpx"
                />
              </template>
            </uv-input>

            <uv-icon
              v-if="column.component === 'Select' && column.key !== 'phone'"
              color="#999999"
              name="arrow-right"
            />
          </view>
        </template>
        <template v-else-if="column.component === 'RadioGroup'">
          <uv-radio-group
            v-bind="column.componentProps || {}"
            v-model="form[column.key]"
          >
            <uv-radio
              v-for="item in column.componentProps.options || []"
              :key="item.value"
              :name="item.value"
              :label="item.text"
            />
          </uv-radio-group>
        </template>
        <template v-else-if="column.component === 'CheckboxGroup'">
          <uv-checkbox-group
            v-model="form[column.key]"
            v-bind="column.componentProps || {}"
          >
            <uv-checkbox
              v-for="item in column.componentProps.options || []"
              :key="item.value"
              :label="item.value"
              :text="item.text"
            />
          </uv-checkbox-group>
        </template>
        <slot
          v-else
          :name="column.slot"
          :formModel="form"
          :field="column.key"
        />
      </uv-form-item>
    </template>

    <slot name="footer">
      <view
        class="flex w-full"
        :style="{
          flexDirection: inline ? 'row' : 'column',
        }"
      >
        <view
          v-if="showReset"
          class="w-full"
          :style="{
            marginRight: inline ? '10px' : '0',
          }"
        >
          <uv-button
            text="重置"
            :customStyle="{
              marginTop: '10px',
              height: '88rpx',
              width: '100%',
              borderRadius: '8rpx',
              borderColor: 'var(--main-color)',
              color: 'var(--main-color)',
            }"
            @tap="reset"
          />
        </view>
        <view v-if="showSubmit" class="w-full">
          <uv-button
            type="primary"
            text="提交"
            :customStyle="{
              marginTop: '10px',
              height: '88rpx',
              width: '100%',
              backgroundColor: 'var(--main-color)',
              borderRadius: '8rpx',
              borderColor: 'var(--main-color)',
            }"
            @tap="submit"
          />
        </view>
      </view>
    </slot>
  </uv-form>
</template>
